package com.kingmed.kmss.common.satoken;

import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.StpUtil;
import com.kingmed.kmss.common.constant.sys.CacheConstants;
import com.kingmed.kmss.common.constant.sys.UserConstants;
import com.kingmed.kmss.common.dto.admin.ums.LoginUserDTO;
import com.kingmed.kmss.common.enums.admin.DeviceType;
import com.kingmed.kmss.common.enums.admin.UserType;
import com.kingmed.kmss.common.exception.NoRecordException;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class LoginHelper {

    public static final String JOIN_CODE = ":";
    public static final String LOGIN_USER_KEY = "loginUser";

    /**
     * 登录系统
     *
     * @param loginUser 登录用户信息
     */
    public static void login(LoginUserDTO loginUser) {
        SaHolder.getStorage().set(LOGIN_USER_KEY, loginUser);
        StpUtil.login(getForLoginId(loginUser));
        loginUser.setToken(StpUtil.getTokenValue());
        //放入redis token-session
        setLoginUser(loginUser);
    }

    /**
     * 登录系统
     *
     * @param loginUser 登录用户信息
     */
    public static void loginWithTimeout(LoginUserDTO loginUser, long timeoutSeconds, String device) {
        SaHolder.getStorage().set(LOGIN_USER_KEY, loginUser);
        SaLoginModel saLoginModel = new SaLoginModel();
        if (timeoutSeconds > 0) {
            saLoginModel.setTimeout(timeoutSeconds);
        }
        if (StringUtils.isNotBlank(device)) {
            saLoginModel.setDevice(device);
        }
        StpUtil.login(getForLoginId(loginUser), saLoginModel);
        loginUser.setToken(StpUtil.getTokenValue());
        //放入redis token-session
        setLoginUser(loginUser);
    }


    private static String getForLoginId(LoginUserDTO loginUser) {
        String userType = loginUser.getUserType();
        Long userId = loginUser.getUserId();
        if (userType == null) {
            userType = "sys_user";
            //throw new IllegalArgumentException("用户类型不能为空");
        }
        if (userId == null) {
            throw new IllegalArgumentException("用户ID不能为空");
        }
        return userType + CacheConstants.LOGINID_JOIN_CODE + userId;
    }

    /**
     * 针对相同用户体系不同设备
     *
     * @param loginUser 登录用户信息
     */
    public static void loginByDevice(LoginUserDTO loginUser, DeviceType deviceType) {
        //想storage缓存
        SaHolder.getStorage().set(LOGIN_USER_KEY, loginUser);
        //向redis插入token和session两条记录
        StpUtil.login(getForLoginId(loginUser), deviceType.getDevice());
        setLoginUser(loginUser);
    }

    /**
     * 设置用户数据(多级缓存)
     */
    public static void setLoginUser(LoginUserDTO loginUser) {
        //放入redis token-session
        StpUtil.getTokenSession().set(LOGIN_USER_KEY, loginUser);
    }

    /**
     * 获取用户(多级缓存)
     */
    public static LoginUserDTO getLoginUser() {
        LoginUserDTO loginUser;
        //先看storage有没有
        loginUser = (LoginUserDTO) SaHolder.getStorage().get(LOGIN_USER_KEY);
        if (loginUser != null) {
            return loginUser;
        }
        //再看是否登录，比如没有提供token
        boolean login = StpUtil.isLogin();
        if (login) {
            //看TokenSession里面有没有
            loginUser = (LoginUserDTO) StpUtil.getTokenSession().get(LOGIN_USER_KEY);
            SaHolder.getStorage().set(LOGIN_USER_KEY, loginUser);
            return loginUser;
        } else
            //改成不传null，防止null point exception，但是判断是否为空时需要BeanUtil.isEmpty(currentUser)
            return new LoginUserDTO();
    }

    public static Long getUserIdByToken() {
        //直接通过token来转换成userId
        String loginId = StpUtil.getLoginIdAsString();
        String userId = null;
        for (UserType value : UserType.values()) {
            if (StringUtils.contains(loginId, value.getUserType())) {
                String[] strs = StringUtils.split(loginId, JOIN_CODE);
                // 用户id
                userId = strs[strs.length - 1];
            }
        }
        if (StringUtils.isBlank(userId)) {
            throw new NoRecordException("登录用户: LoginId异常 => " + loginId);
        }
        return Long.parseLong(userId);
    }


    /**
     * 获取用户账户名
     */
    public static String getUsername() {
        LoginUserDTO loginUser = getLoginUser();
        if (loginUser != null) {
            return getLoginUser().getUsername();
        } else return null;
    }

    /**
     * 获取用户类型(sys_user,app_user)
     */
    public static UserType getUserType() {
        String loginId = StpUtil.getLoginIdAsString();
        return UserType.getUserType(loginId);
    }

    public static boolean isAdmin(LoginUserDTO loginUser) {
        return UserConstants.ADMIN_ID.equals(loginUser.getUserId()) ||
                UserConstants.ADMIN_NAME.equals(loginUser.getUsername());
    }

    public static boolean isAdmin(Long userId) {
        return UserConstants.ADMIN_ID.equals(userId);
    }

    public static boolean isAdmin(String username) {
        return UserConstants.ADMIN_NAME.equals(username);
    }

    public static boolean isAdmin() {
        return isAdmin(getUserIdByToken());
    }

}
